3e5a4e653U6cELGv528IxOLHvCq8iA xenolinux-2.4.25-sparse/arch/xen/kernel/irq.c
3e5a4e65muT6SU3ck47IP87Q7Ti5hA xenolinux-2.4.25-sparse/arch/xen/kernel/ldt.c
4051db84bZeRX7a_Kh6VyyDuT5FOIg xenolinux-2.4.25-sparse/arch/xen/kernel/pci-dma.c
-4051db89iiHs38tWGkoW_RukNyaBHw xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.c
-4051db8dJYX86ZCLA-WfTW2dAyrehw xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h
-4051db91BenvDZEMZxQCGkQyJYoG5w xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c
4051db95N9N99FjsRwi49YKUNHWI8A xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c
3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ xenolinux-2.4.25-sparse/arch/xen/kernel/process.c
3e5a4e66tR-qJMLj3MppcKqmvuI2XQ xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
****************************************************************************
- * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ * (c) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ * (c) 2004 - Keir Fraser - University of Cambridge
****************************************************************************
- *
- * File: phys_dev.c
- * Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
- * Date: Feb 2004
*
* Description: allows a domain to access devices on the PCI bus
*
#include <hypervisor-ifs/hypervisor-if.h>
#include <hypervisor-ifs/physdev.h>
+/* Called by PHYSDEV_PCI_INITIALISE_DEVICE to finalise IRQ routing. */
+extern void pcibios_enable_irq(struct pci_dev *dev);
+
#if 1
#define DBG(_x...)
#else
* error is flagged.
*/
static int do_base_address_access(phys_dev_t *pdev, int acc,
- int seg, int bus, int dev, int func,
+ int bus, int dev, int func,
int reg, int len, u32 *val)
{
int idx, st_bit, ret = -EINVAL;
clear_bit(st_bit, &pdev->state);
/* check if guest tries to restore orig value */
- ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
+ ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val);
if ( *val != orig_val )
{
printk("caution: guest tried to change base address range.\n");
if ( !test_bit(st_bit, &pdev->state) )
{
/* just read and return */
- ret = pci_config_read(seg, bus, dev, func, reg, len, val);
+ ret = pci_config_read(0, bus, dev, func, reg, len, val);
}
else
{
/* fake value */
- ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
+ ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val);
sz = res->end - res->start;
* pretty much the same as a above
*/
static int do_rom_address_access(phys_dev_t *pdev, int acc,
- int seg, int bus, int dev, int func,
- int reg, int len, u32 *val)
+ int bus, int dev, int func,
+ int reg, int len, u32 *val)
{
int st_bit, ret = -EINVAL;
u32 orig_val, sz;
clear_bit(st_bit, &pdev->state);
/* check if guest tries to restore orig value */
- ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
+ ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val);
if ( (*val != orig_val) )
{
if (*val != 0x00000000 )
if ( !test_bit(st_bit, &pdev->state) )
{
/* just read and return */
- ret = pci_config_read(seg, bus, dev, func, reg, len, val);
+ ret = pci_config_read(0, bus, dev, func, reg, len, val);
}
else
{
/* fake value */
- ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
+ ret = pci_config_read(0, bus, dev, func, reg, len, &orig_val);
sz = res->end - res->start;
*val = 0xffffffff;
/* leave bit 0 untouched */
* For some registers for read-only devices (e.g. address base registers)
* we need to maintain a state machine.
*/
-static long pci_cfgreg_read(int seg, int bus, int dev, int func, int reg,
+static long pci_cfgreg_read(int bus, int dev, int func, int reg,
int len, u32 *val)
{
- int ret = 0;
+ int ret;
phys_dev_t *pdev;
- ret = check_dev_acc(current, bus, dev, func, &pdev);
- if ( ret != 0 )
+ if ( (ret = check_dev_acc(current, bus, dev, func, &pdev)) != 0 )
return ret;
- /* fake out read requests for some registers */
- switch (reg)
+ /* Fake out read requests for some registers. */
+ switch ( reg )
{
case PCI_BASE_ADDRESS_0:
case PCI_BASE_ADDRESS_1:
case PCI_BASE_ADDRESS_3:
case PCI_BASE_ADDRESS_4:
case PCI_BASE_ADDRESS_5:
- ret = do_base_address_access (pdev, ACC_READ, seg, bus, dev,
- func, reg, len, val);
- return ret;
+ ret = do_base_address_access(pdev, ACC_READ, bus, dev,
+ func, reg, len, val);
break;
+
case PCI_ROM_ADDRESS:
- ret = do_rom_address_access (pdev, ACC_READ, seg, bus, dev,
- func, reg, len, val);
- return ret;
+ ret = do_rom_address_access(pdev, ACC_READ, bus, dev,
+ func, reg, len, val);
break;
+
+ case PCI_INTERRUPT_LINE:
+ ret = pdev->dev->irq;
+ break;
+
default:
+ ret = pci_config_read(0, bus, dev, func, reg, len, val);
+ DBG("pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
+ bus, dev, func, reg, len, *val);
break;
}
- ret = pci_config_read(seg, bus, dev, func, reg, len, val);
-
- DBG("pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
- bus, dev, func, reg, len, *val);
return ret;
}
* for some registers a state machine is maintained to fake out r/w access.
* By default no write access is allowed but we may change that in the future.
*/
-static long pci_cfgreg_write(int seg, int bus, int dev, int func, int reg,
+static long pci_cfgreg_write(int bus, int dev, int func, int reg,
int len, u32 val)
{
- int ret = 0;
+ int ret;
phys_dev_t *pdev;
- ret = check_dev_acc(current, bus, dev, func, &pdev);
- if ( ret != 0 )
+ if ( (ret = check_dev_acc(current, bus, dev, func, &pdev)) != 0 )
return ret;
/* special treatment for some registers */
case PCI_BASE_ADDRESS_3:
case PCI_BASE_ADDRESS_4:
case PCI_BASE_ADDRESS_5:
- ret = do_base_address_access (pdev, ACC_WRITE, seg, bus, dev,
+ ret = do_base_address_access (pdev, ACC_WRITE, bus, dev,
func, reg, len, &val);
return ret;
break;
+
case PCI_ROM_ADDRESS:
- ret = do_rom_address_access (pdev, ACC_WRITE, seg, bus, dev,
+ ret = do_rom_address_access (pdev, ACC_WRITE, bus, dev,
func, reg, len, &val);
return ret;
break;
-#if 0
- case 0xe0: /* XXX some device drivers seem to write to this.... */
- printk("pci write hack allowed %02x:%02x:%02x: "
- "reg=0x%02x len=0x%02x val=0x%08x\n",
- bus, dev, func, reg, len, val);
- break;
-#endif
+
default:
- //if ( pdev->flags != ACC_WRITE )
- /* XXX for debug we disallow all write access */
+ if ( pdev->flags != ACC_WRITE )
{
printk("pci write not allowed %02x:%02x:%02x: "
"reg=0x%02x len=0x%02x val=0x%08x\n",
bus, dev, func, reg, len, val);
- return -EPERM;
+ ret = -EPERM;
+ }
+ else
+ {
+ ret = pci_config_write(0, bus, dev, func, reg, len, val);
+ DBG("pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
+ bus, dev, func, reg, len, val);
}
break;
}
- ret = pci_config_write(seg, bus, dev, func, reg, len, val);
-
- DBG("pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
- bus, dev, func, reg, len, val);
return ret;
}
-/*
- *
- * Interrupt handling
- *
- */
-
-/*
- * return the IRQ xen assigned to the device.
- * This may be different to what is in the PCI confic space!
- * XXX RN: I'm not sure we need this. we could just intercept PCI config
- * reads on PCI_INTERRUPT_LINE and return the correct value.
- */
-static long pci_find_irq(int seg, int bus, int dev, int func, u32 *val)
+static long pci_probe_root_buses(u32 *busmask)
{
- int ret = 0;
phys_dev_t *pdev;
+ struct list_head *tmp;
- ret = check_dev_acc(current, bus, dev, func, &pdev);
- if ( ret != 0 )
- return ret;
+ memset(busmask, 0, 256/8);
+
+ list_for_each ( tmp, ¤t->pcidev_list )
+ {
+ pdev = list_entry(tmp, phys_dev_t, node);
+ set_bit(pdev->dev->bus->number, busmask);
+ }
- *val = pdev->dev->irq;
return 0;
}
/*
- * demux hypervisor call.
+ * Demuxing hypercall.
*/
long do_physdev_op(physdev_op_t *uop)
{
+ phys_dev_t *pdev;
physdev_op_t op;
long ret;
switch ( op.cmd )
{
- case PHYSDEVOP_CFGREG_READ:
- ret = pci_cfgreg_read(op.u.cfg_read.seg, op.u.cfg_read.bus,
- op.u.cfg_read.dev, op.u.cfg_read.func,
- op.u.cfg_read.reg, op.u.cfg_read.len,
- &op.u.cfg_read.value);
+ case PHYSDEVOP_PCI_CFGREG_READ:
+ ret = pci_cfgreg_read(op.u.pci_cfgreg_read.bus,
+ op.u.pci_cfgreg_read.dev,
+ op.u.pci_cfgreg_read.func,
+ op.u.pci_cfgreg_read.reg,
+ op.u.pci_cfgreg_read.len,
+ &op.u.pci_cfgreg_read.value);
break;
- case PHYSDEVOP_CFGREG_WRITE:
- ret = pci_cfgreg_write(op.u.cfg_write.seg, op.u.cfg_write.bus,
- op.u.cfg_write.dev, op.u.cfg_write.func,
- op.u.cfg_write.reg, op.u.cfg_write.len,
- op.u.cfg_write.value);
+ case PHYSDEVOP_PCI_CFGREG_WRITE:
+ ret = pci_cfgreg_write(op.u.pci_cfgreg_write.bus,
+ op.u.pci_cfgreg_write.dev,
+ op.u.pci_cfgreg_write.func,
+ op.u.pci_cfgreg_write.reg,
+ op.u.pci_cfgreg_write.len,
+ op.u.pci_cfgreg_write.value);
break;
- case PHYSDEVOP_FIND_IRQ:
- ret = pci_find_irq(op.u.find_irq.seg, op.u.find_irq.bus,
- op.u.find_irq.dev, op.u.find_irq.func,
- &op.u.find_irq.irq);
+ case PHYSDEVOP_PCI_INITIALISE_DEVICE:
+ if ( (ret = check_dev_acc(current,
+ op.u.pci_initialise_device.bus,
+ op.u.pci_initialise_device.dev,
+ op.u.pci_initialise_device.func,
+ &pdev)) == 0 )
+ pcibios_enable_irq(pdev->dev);
+ break;
+
+ case PHYSDEVOP_PCI_PROBE_ROOT_BUSES:
+ ret = pci_probe_root_buses(op.u.pci_probe_root_buses.busmask);
break;
case PHYSDEVOP_UNMASK_IRQ:
}
-/*
- * Domain 0 has read access to all devices.
- * XXX this is a bit of a hack
- */
+/* Domain 0 has read access to all devices. */
void physdev_init_dom0(struct task_struct *p)
{
struct pci_dev *dev;
/* add device */
pdev = kmalloc(sizeof(phys_dev_t), GFP_KERNEL);
pdev->dev = dev;
- pdev->flags = ACC_READ;
+ pdev->flags = ACC_WRITE;
pdev->state = 0;
pdev->owner = p;
list_add(&pdev->node, &p->pcidev_list);
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
****************************************************************************
- * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ * (c) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ * (c) 2004 - Keir Fraser - University of Cambridge
****************************************************************************
- *
- * File: physdev.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Date: Feb 2004
- *
* Description: Interface for domains to access physical devices on the PCI bus
*/
#ifndef __HYPERVISOR_IFS_PHYSDEV_H__
#define __HYPERVISOR_IFS_PHYSDEV_H__
-/*
- * Commands to HYPERVISOR_physdev_op()
- */
-#define PHYSDEVOP_CFGREG_READ 0
-#define PHYSDEVOP_CFGREG_WRITE 1
-#define PHYSDEVOP_FIND_IRQ 2
-#define PHYSDEVOP_UNMASK_IRQ 3
+/* Commands to HYPERVISOR_physdev_op() */
+#define PHYSDEVOP_PCI_CFGREG_READ 0
+#define PHYSDEVOP_PCI_CFGREG_WRITE 1
+#define PHYSDEVOP_PCI_INITIALISE_DEVICE 2
+#define PHYSDEVOP_PCI_PROBE_ROOT_BUSES 3
+#define PHYSDEVOP_UNMASK_IRQ 4
-/* read pci config */
-typedef struct physdevop_cfgreg_read_st
+/* Read from PCI configuration space. */
+typedef struct physdevop_pci_cfgreg_read_st
{
- int seg; /* IN */
int bus; /* IN */
int dev; /* IN */
int func; /* IN */
int reg; /* IN */
int len; /* IN */
u32 value; /* OUT */
-} physdevop_cfgreg_read_t;
+} physdevop_pci_cfgreg_read_t;
-/* write pci config */
-typedef struct physdevop_cfgred_write_st
+/* Write to PCI configuration space. */
+typedef struct physdevop_pci_cfgreg_write_st
{
- int seg; /* IN */
int bus; /* IN */
int dev; /* IN */
int func; /* IN */
int reg; /* IN */
int len; /* IN */
u32 value; /* IN */
-} physdevop_cfgreg_write_t;
+} physdevop_pci_cfgreg_write_t;
-/* get the real IRQ for a device */
-typedef struct physdevop_find_irq_st
+/* Do final initialisation of a PCI device (e.g., last-moment IRQ routing). */
+typedef struct physdevop_pci_initialise_device_st
{
- int seg; /* IN */
int bus; /* IN */
int dev; /* IN */
int func; /* IN */
- u32 irq; /* OUT */
-} physdevop_find_irq_t;
+} physdevop_pci_initialise_device_t;
+
+/* Find the root buses for subsequent scanning. */
+typedef struct physdevop_pci_probe_root_buses_st
+{
+ u32 busmask[256/32]; /* OUT */
+} physdevop_pci_probe_root_buses_t;
typedef struct _physdev_op_st
{
unsigned long cmd;
-
- /* command parameters */
union
{
- physdevop_cfgreg_read_t cfg_read;
- physdevop_cfgreg_write_t cfg_write;
- physdevop_find_irq_t find_irq;
+ physdevop_pci_cfgreg_read_t pci_cfgreg_read;
+ physdevop_pci_cfgreg_write_t pci_cfgreg_write;
+ physdevop_pci_initialise_device_t pci_initialise_device;
+ physdevop_pci_probe_root_buses_t pci_probe_root_buses;
} u;
} physdev_op_t;
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_7000FASST is not set
# CONFIG_SCSI_ACARD is not set
-CONFIG_SCSI_AHA152X=y
-CONFIG_SCSI_AHA1542=y
-CONFIG_SCSI_AHA1740=y
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
CONFIG_SCSI_AACRAID=y
# CONFIG_SCSI_AIC7XXX is not set
CONFIG_SCSI_AIC79XX=y
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
-CONFIG_SCSI_GENERIC_NCR5380=y
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_GENERIC_NCR53C400 is not set
-CONFIG_SCSI_G_NCR5380_PORT=y
+# CONFIG_SCSI_G_NCR5380_PORT is not set
# CONFIG_SCSI_G_NCR5380_MEM is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
i386_ksyms.o i387.o evtchn.o pci-dma.o
ifdef CONFIG_PCI
-obj-y += pci-i386.o pci-pc.o pci-irq.o
+obj-y += pci-i386.o pci-pc.o
endif
include $(TOPDIR)/Rules.make
+++ /dev/null
-/*
- * Low-Level PCI Access for i386 machines
- *
- * Copyright 1993, 1994 Drew Eckhardt
- * Visionary Computing
- * (Unix and Linux consulting and custom programming)
- * Drew@Colorado.EDU
- * +1 (303) 786-7975
- *
- * Drew's work was sponsored by:
- * iX Multiuser Multitasking Magazine
- * Hannover, Germany
- * hm@ix.de
- *
- * Copyright 1997--2000 Martin Mares <mj@ucw.cz>
- *
- * For more information, please consult the following manuals (look at
- * http://www.pcisig.com/ for how to get them):
- *
- * PCI BIOS Specification
- * PCI Local Bus Specification
- * PCI to PCI Bridge Specification
- * PCI System Design Guide
- *
- *
- * CHANGELOG :
- * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
- * Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
- *
- * Jan 5, 1995 : Modified to probe PCI hardware at boot time by Frederic
- * Potter, potter@cao-vlsi.ibp.fr
- *
- * Jan 10, 1995 : Modified to store the information about configured pci
- * devices into a list, which can be accessed via /proc/pci by
- * Curtis Varner, cvarner@cs.ucr.edu
- *
- * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
- * Alpha version. Intel & UMC chipset support only.
- *
- * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
- * moved to drivers/pci/pci.c.
- *
- * Dec 7, 1996 : Added support for direct configuration access of boards
- * with Intel compatible access schemes (tsbogend@alpha.franken.de)
- *
- * Feb 3, 1997 : Set internal functions to static, save/restore flags
- * avoid dead locks reading broken PCI BIOS, werner@suse.de
- *
- * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
- * (mj@atrey.karlin.mff.cuni.cz)
- *
- * May 7, 1997 : Added some missing cli()'s. [mj]
- *
- * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
- * (paubert@iram.es)
- *
- * Aug 2, 1997 : Split to PCI BIOS handling and direct PCI access parts
- * and cleaned it up... Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- *
- * Feb 6, 1998 : No longer using BIOS to find devices and device classes. [mj]
- *
- * May 1, 1998 : Support for peer host bridges. [mj]
- *
- * Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space
- * can be accessed from interrupts even on SMP systems. [mj]
- *
- * August 1998 : Better support for peer host bridges and more paranoid
- * checks for direct hardware access. Ugh, this file starts to look as
- * a large gallery of common hardware bug workarounds (watch the comments)
- * -- the PCI specs themselves are sane, but most implementors should be
- * hit hard with \hammer scaled \magstep5. [mj]
- *
- * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
- *
- * Feb 8, 1999 : Added UM8886BF I/O address fixup. [mj]
- *
- * August 1999 : New resource management and configuration access stuff. [mj]
- *
- * Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges.
- * Based on ideas by Chris Frantz and David Hinds. [mj]
- *
- * Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi
- * for a lot of patience during testing. [mj]
- *
- * Oct 8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj]
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-
-#include "pci-i386.h"
-
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void
-pcibios_align_resource(void *data, struct resource *res,
- unsigned long size, unsigned long align)
-{
- if (res->flags & IORESOURCE_IO) {
- unsigned long start = res->start;
-
- if (start & 0x300) {
- start = (start + 0x3ff) & ~0x3ff;
- res->start = start;
- }
- }
-}
-
-
-/*
- * Handle resources of PCI devices. If the world were perfect, we could
- * just allocate all the resource regions and do nothing more. It isn't.
- * On the other hand, we cannot just re-allocate all devices, as it would
- * require us to know lots of host bridge internals. So we attempt to
- * keep as much of the original configuration as possible, but tweak it
- * when it's found to be wrong.
- *
- * Known BIOS problems we have to work around:
- * - I/O or memory regions not configured
- * - regions configured, but not enabled in the command register
- * - bogus I/O addresses above 64K used
- * - expansion ROMs left enabled (this may sound harmless, but given
- * the fact the PCI specs explicitly allow address decoders to be
- * shared between expansion ROMs and other resource regions, it's
- * at least dangerous)
- *
- * Our solution:
- * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
- * This gives us fixed barriers on where we can allocate.
- * (2) Allocate resources for all enabled devices. If there is
- * a collision, just mark the resource as unallocated. Also
- * disable expansion ROMs during this step.
- * (3) Try to allocate resources for disabled devices. If the
- * resources were assigned correctly, everything goes well,
- * if they weren't, they won't disturb allocation of other
- * resources.
- * (4) Assign new addresses to resources which were either
- * not configured at all or misconfigured. If explicitly
- * requested by the user, configure expansion ROM address
- * as well.
- */
-
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
-{
- struct list_head *ln;
- struct pci_bus *bus;
- struct pci_dev *dev;
- int idx;
- struct resource *r, *pr;
-
- /* Depth-First Search on bus tree */
- for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
- bus = pci_bus_b(ln);
- if ((dev = bus->self)) {
- printk("alloc bus res: %s\n", dev->slot_name);
- for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
- r = &dev->resource[idx];
- if (!r->start)
- {
- printk(" res1: 0x%08lx-0x%08lx f=%lx\n",
- r->start, r->end, r->flags);
-
- continue;
- }
- pr = pci_find_parent_resource(dev, r);
- if (!pr || request_resource(pr, r) < 0)
- printk(KERN_ERR "PCI: Cannot allocate resource region %d "
- "of bridge %s (%p)\n", idx, dev->slot_name, pr);
- printk(" res2: %08lx-%08lx f=%lx\n",
- r->start, r->end, r->flags);
- }
- }
- pcibios_allocate_bus_resources(&bus->children);
- }
-}
-
-static void __init pcibios_allocate_resources(int pass)
-{
- struct pci_dev *dev;
- int idx, disabled;
- u16 command;
- struct resource *r, *pr;
-
- pci_for_each_dev(dev) {
- pci_read_config_word(dev, PCI_COMMAND, &command);
- for(idx = 0; idx < 6; idx++) {
- r = &dev->resource[idx];
- if (r->parent) /* Already allocated */
- continue;
- if (!r->start) /* Address not assigned at all */
- continue;
- if (r->flags & IORESOURCE_IO)
- disabled = !(command & PCI_COMMAND_IO);
- else
- disabled = !(command & PCI_COMMAND_MEMORY);
- if (pass == disabled) {
- printk("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d) (%s)\n",
- r->start, r->end, r->flags, disabled, pass, dev->slot_name);
- pr = pci_find_parent_resource(dev, r);
- if (!pr || request_resource(pr, r) < 0) {
- printk(KERN_ERR "PCI: Cannot allocate resource region %d"
- " of device %s (%p)\n", idx, dev->slot_name, pr);
- /* We'll assign a new address later */
- r->end -= r->start;
- r->start = 0;
- }
- }
- }
- if (!pass) {
- r = &dev->resource[PCI_ROM_RESOURCE];
- if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
- /* Turn the ROM off, leave the resource region, but keep it unregistered. */
- u32 reg;
- printk("PCI: Switching off ROM of %s\n", dev->slot_name);
- r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_read_config_dword(dev, dev->rom_base_reg, ®);
- pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
- }
- }
- }
-}
-
-static void __init pcibios_assign_resources(void)
-{
- struct pci_dev *dev;
- int idx;
- struct resource *r;
-
- pci_for_each_dev(dev) {
- int class = dev->class >> 8;
-
- /* Don't touch classless devices and host bridges */
- if (!class || class == PCI_CLASS_BRIDGE_HOST)
- continue;
-
- for(idx=0; idx<6; idx++) {
- r = &dev->resource[idx];
-
- /*
- * Don't touch IDE controllers and I/O ports of video cards!
- */
- if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
- (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
- continue;
-
- /*
- * We shall assign a new address to this resource, either because
- * the BIOS forgot to do so or because we have decided the old
- * address was unusable for some reason.
- */
- if (!r->start && r->end)
- pci_assign_resource(dev, idx);
- }
-
- if (pci_probe & PCI_ASSIGN_ROMS) {
- r = &dev->resource[PCI_ROM_RESOURCE];
- r->end -= r->start;
- r->start = 0;
- if (r->end)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
- }
- }
-}
-
-void __init pcibios_set_cacheline_size(void)
-{
- struct cpuinfo_x86 *c = &boot_cpu_data;
-
- pci_cache_line_size = 32 >> 2;
- if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
- pci_cache_line_size = 64 >> 2; /* K7 & K8 */
- else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
- pci_cache_line_size = 128 >> 2; /* P4 */
-}
-
-void __init pcibios_resource_survey(void)
-{
- DBG("PCI: Allocating resources\n");
- pcibios_allocate_bus_resources(&pci_root_buses);
- pcibios_allocate_resources(0);
- pcibios_allocate_resources(1);
- pcibios_assign_resources();
-}
-
-int pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
- u16 cmd, old_cmd;
- int idx;
- struct resource *r;
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- old_cmd = cmd;
- for(idx=0; idx<6; idx++) {
- /* Only set up the requested stuff */
- if (!(mask & (1<<idx)))
- continue;
-
- r = &dev->resource[idx];
- if (!r->start && r->end) {
- printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
- return -EINVAL;
- }
- if (r->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- if (r->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
- if (dev->resource[PCI_ROM_RESOURCE].start)
- cmd |= PCI_COMMAND_MEMORY;
- if (cmd != old_cmd) {
- printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
- return 0;
-}
-
-/*
- * If we set up a device for bus mastering, we need to check the latency
- * timer as certain crappy BIOSes forget to set it properly.
- */
-unsigned int pcibios_max_latency = 255;
-
-void pcibios_set_master(struct pci_dev *dev)
-{
- u8 lat;
- pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
- if (lat < 16)
- lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
- else if (lat > pcibios_max_latency)
- lat = pcibios_max_latency;
- else
- return;
- printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-}
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state, int write_combine)
-{
- unsigned long prot;
-
- /* I/O space cannot be accessed via normal processor loads and
- * stores on this platform.
- */
- if (mmap_state == pci_mmap_io)
- return -EINVAL;
-
- /* Leave vm_pgoff as-is, the PCI space address is the physical
- * address on this platform.
- */
- vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
-
- prot = pgprot_val(vma->vm_page_prot);
- if (boot_cpu_data.x86 > 3)
- prot |= _PAGE_PCD | _PAGE_PWT;
- vma->vm_page_prot = __pgprot(prot);
-
- /* Write-combine setting is ignored, it is changed via the mtrr
- * interfaces on this platform.
- */
- if (remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
-}
+++ /dev/null
-/*
- * Low-Level PCI Access for i386 machines.
- *
- * (c) 1999 Martin Mares <mj@ucw.cz>
- */
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-#define PCI_PROBE_BIOS 0x0001
-#define PCI_PROBE_CONF1 0x0002
-#define PCI_PROBE_CONF2 0x0004
-#define PCI_NO_SORT 0x0100
-#define PCI_BIOS_SORT 0x0200
-#define PCI_NO_CHECKS 0x0400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-#define PCI_ASSIGN_ALL_BUSSES 0x4000
-
-extern unsigned int pci_probe;
-
-/* pci-i386.c */
-
-extern unsigned int pcibios_max_latency;
-extern u8 pci_cache_line_size;
-
-void pcibios_resource_survey(void);
-void pcibios_set_cacheline_size(void);
-int pcibios_enable_resources(struct pci_dev *, int);
-
-/* pci-pc.c */
-
-extern int pcibios_last_bus;
-extern struct pci_bus *pci_root_bus;
-extern struct pci_ops *pci_root_ops;
-
-/* pci-irq.c */
-
-struct irq_info {
- u8 bus, devfn; /* Bus, device and function */
- struct {
- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
- u16 bitmap; /* Available IRQs */
- } __attribute__((packed)) irq[4];
- u8 slot; /* Slot number, 0=onboard */
- u8 rfu;
-} __attribute__((packed));
-
-struct irq_routing_table {
- u32 signature; /* PIRQ_SIGNATURE should be here */
- u16 version; /* PIRQ_VERSION */
- u16 size; /* Table size in bytes */
- u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
- u32 miniport_data; /* Crap */
- u8 rfu[11];
- u8 checksum; /* Modulo 256 checksum must give zero */
- struct irq_info slots[0];
-} __attribute__((packed));
-
-extern unsigned int pcibios_irq_mask;
-
-void pcibios_irq_init(void);
-void pcibios_fixup_irqs(void);
-void pcibios_enable_irq(struct pci_dev *dev);
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: phys_dev.c
- * Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
- * Date: Mar 2004
- *
- * Description: XenoLinux wrappers for PCI interrupt handling.
- * very simple since someone else is doing all the hard bits
- */
-
-
-/*
- * Low-Level PCI Support for PC -- Routing of Interrupts
- *
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include "pci-i386.h"
-
-#include <asm/hypervisor-ifs/physdev.h>
-
-unsigned int pcibios_irq_mask = 0xfff8;
-
-void eisa_set_level_irq(unsigned int irq)
-{
- /* dummy */
-}
-
-void __init pcibios_irq_init(void)
-{
- printk("PCI: IRQ init\n");
-}
-
-void __init pcibios_fixup_irqs(void)
-{
- struct pci_dev *dev;
- physdev_op_t op;
- int ret;
-
-
- printk("PCI: IRQ fixup\n");
- pci_for_each_dev(dev) {
-
- op.cmd = PHYSDEVOP_FIND_IRQ;
- op.u.find_irq.seg = 0;
- op.u.find_irq.bus = dev->bus->number;
- op.u.find_irq.dev = PCI_SLOT(dev->devfn);
- op.u.find_irq.func = PCI_FUNC(dev->devfn);
-
- if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
- {
- printk(KERN_ALERT "pci find irq error\n");
- return;
- }
-
- dev->irq = op.u.find_irq.irq;
- printk(KERN_INFO "PCI IRQ: [%02x:%02x:%02x] -> %d\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn), dev->irq);
- }
- return;
-}
-
-void pcibios_penalize_isa_irq(int irq)
-{
- /* dummy */
-}
-
-void pcibios_enable_irq(struct pci_dev *dev)
-{
- u8 pin;
-
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-
- if (pin && !dev->irq) {
- printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of "
- "device %s.\n", 'A' + pin - 1, dev->slot_name);
- }
-}
*
* (c) 1999--2000 Martin Mares <mj@ucw.cz>
*
- * adjusted to use Xen's interface by Rolf Neugebauer
+ * Adjusted to use Xen's interface by Rolf Neugebauer, Intel Research Cambridge
+ * Further modifications by Keir Fraser, University of Cambridge
*/
#include <linux/config.h>
#include "pci-i386.h"
-int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus = NULL;
-struct pci_ops *pci_root_ops = NULL;
-
-int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
-int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
-
-static int pci_using_acpi_prt = 0;
-
/*
- * This interrupt-safe spinlock protects all accesses to PCI
- * configuration space.
+ * NB. The following interface functions are not included here:
+ * 1. void eisa_set_level_irq(unsigned int irq)
+ * 2. irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
+ * 3. int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
+ * All are used by the ACPI driver. This should be ported to Xen if it is
+ * ever required -- Xen is the ultimate source for IRQ-routing knowledge.
*/
-static spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
+
+struct pci_ops *pci_root_ops = NULL;
+
+int (*pci_config_read)(int seg, int bus, int dev, int fn,
+ int reg, int len, u32 *value) = NULL;
+int (*pci_config_write)(int seg, int bus, int dev, int fn,
+ int reg, int len, u32 value) = NULL;
unsigned int pci_probe = PCI_PROBE_BIOS;
-/*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
+struct pci_fixup pcibios_fixups[] = { { 0 } };
-static int pci_confx_read (int seg, int bus, int dev, int fn, int reg,
- int len, u32 *value)
+static int pci_confx_read(int seg, int bus, int dev, int fn, int reg,
+ int len, u32 *value)
{
int ret;
physdev_op_t op;
if (bus > 255 || dev > 31 || fn > 7 || reg > 255)
return -EINVAL;
- op.cmd = PHYSDEVOP_CFGREG_READ;
- op.u.cfg_read.seg = seg;
- op.u.cfg_read.bus = bus;
- op.u.cfg_read.dev = dev;
- op.u.cfg_read.func = fn;
- op.u.cfg_read.reg = reg;
- op.u.cfg_read.len = len;
+ op.cmd = PHYSDEVOP_PCI_CFGREG_READ;
+ op.u.pci_cfgreg_read.bus = bus;
+ op.u.pci_cfgreg_read.dev = dev;
+ op.u.pci_cfgreg_read.func = fn;
+ op.u.pci_cfgreg_read.reg = reg;
+ op.u.pci_cfgreg_read.len = len;
if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
- {
- //printk(KERN_ALERT "pci config read error\n");
return ret;
- }
- *value = op.u.cfg_read.value;
+ *value = op.u.pci_cfgreg_read.value;
return 0;
}
-static int pci_confx_write (int seg, int bus, int dev, int fn, int reg,
- int len, u32 value)
+static int pci_confx_write(int seg, int bus, int dev, int fn, int reg,
+ int len, u32 value)
{
int ret;
physdev_op_t op;
if ((bus > 255 || dev > 31 || fn > 7 || reg > 255))
return -EINVAL;
- op.cmd = PHYSDEVOP_CFGREG_WRITE;
- op.u.cfg_write.seg = seg;
- op.u.cfg_write.bus = bus;
- op.u.cfg_write.dev = dev;
- op.u.cfg_write.func = fn;
- op.u.cfg_write.reg = reg;
- op.u.cfg_write.len = len;
- op.u.cfg_write.value = value;
+ op.cmd = PHYSDEVOP_PCI_CFGREG_WRITE;
+ op.u.pci_cfgreg_write.bus = bus;
+ op.u.pci_cfgreg_write.dev = dev;
+ op.u.pci_cfgreg_write.func = fn;
+ op.u.pci_cfgreg_write.reg = reg;
+ op.u.pci_cfgreg_write.len = len;
+ op.u.pci_cfgreg_write.value = value;
if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
- {
- //printk(KERN_ALERT "pci config write error\n");
return ret;
- }
return 0;
}
-static int pci_confx_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+static int pci_confx_read_config_byte(struct pci_dev *dev,
+ int where, u8 *value)
{
int result;
u32 data;
return result;
}
-static int pci_confx_read_config_word(struct pci_dev *dev, int where, u16 *value)
+static int pci_confx_read_config_word(struct pci_dev *dev,
+ int where, u16 *value)
{
int result;
u32 data;
return result;
}
-static int pci_confx_read_config_dword(struct pci_dev *dev, int where, u32 *value)
+static int pci_confx_read_config_dword(struct pci_dev *dev,
+ int where, u32 *value)
{
return pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 4, value);
}
-static int pci_confx_write_config_byte(struct pci_dev *dev, int where, u8 value)
+static int pci_confx_write_config_byte(struct pci_dev *dev,
+ int where, u8 value)
{
return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 1, value);
}
-static int pci_confx_write_config_word(struct pci_dev *dev, int where, u16 value)
+static int pci_confx_write_config_word(struct pci_dev *dev,
+ int where, u16 value)
{
return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 2, value);
}
-static int pci_confx_write_config_dword(struct pci_dev *dev, int where, u32 value)
+static int pci_confx_write_config_dword(struct pci_dev *dev,
+ int where, u32 value)
{
return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 4, value);
}
-static struct pci_ops pci_direct_confx = {
+static struct pci_ops pci_conf_xen = {
pci_confx_read_config_byte,
pci_confx_read_config_word,
pci_confx_read_config_dword,
pci_confx_write_config_dword
};
-
-
-static struct pci_ops * __devinit pci_check_xen(void)
-{
- unsigned long flags;
-
- __save_flags(flags); __cli();
-
- printk(KERN_INFO "PCI: Using Xen interface\n");
-
- __restore_flags(flags);
-
- return &pci_direct_confx;
-}
-
-struct pci_fixup pcibios_fixups[] = { {0}};
-
-
-struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
-{
- return NULL;
-}
-
-int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
-{
- return 0;
+void pcibios_penalize_isa_irq(int irq)
+{
+ /* nothing */
}
-/*
- * Several buggy motherboards address only 16 devices and mirror
- * them to next 16 IDs. We try to detect this `feature' on all
- * primary buses (those containing host bridges as they are
- * expected to be unique) and remove the ghost devices.
- */
-
-static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
+void __devinit pcibios_fixup_bus(struct pci_bus *b)
{
- struct list_head *ln, *mn;
- struct pci_dev *d, *e;
- int mirror = PCI_DEVFN(16,0);
- int seen_host_bridge = 0;
- int i;
-
- DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
- for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
- d = pci_dev_b(ln);
- if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
- seen_host_bridge++;
- for (mn=ln->next; mn != &b->devices; mn=mn->next) {
- e = pci_dev_b(mn);
- if (e->devfn != d->devfn + mirror ||
- e->vendor != d->vendor ||
- e->device != d->device ||
- e->class != d->class)
- continue;
- for(i=0; i<PCI_NUM_RESOURCES; i++)
- if (e->resource[i].start != d->resource[i].start ||
- e->resource[i].end != d->resource[i].end ||
- e->resource[i].flags != d->resource[i].flags)
- continue;
- break;
- }
- if (mn == &b->devices)
- return;
- }
- if (!seen_host_bridge)
- return;
- printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number);
-
- ln = &b->devices;
- while (ln->next != &b->devices) {
- d = pci_dev_b(ln->next);
- if (d->devfn >= mirror) {
- list_del(&d->global_list);
- list_del(&d->bus_list);
- kfree(d);
- } else
- ln = ln->next;
- }
-}
-
-/*
- * Discover remaining PCI buses in case there are peer host bridges.
- * We use the number of last PCI bus provided by the PCI BIOS.
- */
-static void __devinit pcibios_fixup_peer_bridges(void)
-{
- int n;
- struct pci_bus bus;
- struct pci_dev dev;
- u16 l;
-
- if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
- return;
- DBG("PCI: Peer bridge fixup\n");
- for (n=0; n <= pcibios_last_bus; n++) {
- if (pci_bus_exists(&pci_root_buses, n))
- continue;
- bus.number = n;
- bus.ops = pci_root_ops;
- dev.bus = &bus;
- for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
- if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
- l != 0x0000 && l != 0xffff) {
- DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
- printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
- pci_scan_bus(n, pci_root_ops, NULL);
- break;
- }
- }
-}
-
-
-/*
- * Called after each bus is probed, but before its children
- * are examined.
- */
-
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
-{
- pcibios_fixup_ghosts(b);
pci_read_bridge_bases(b);
- return;
}
struct pci_bus * __devinit pcibios_scan_root(int busnum)
struct list_head *list;
struct pci_bus *bus;
- list_for_each(list, &pci_root_buses) {
+ list_for_each ( list, &pci_root_buses )
+ {
bus = pci_bus_b(list);
- if (bus->number == busnum) {
- /* Already scanned */
+ if ( bus->number == busnum )
return bus;
- }
}
printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);
-
return pci_scan_bus(busnum, pci_root_ops, NULL);
}
-void __devinit pcibios_config_init(void)
+void __init pcibios_init(void)
{
- /*
- * Try all known PCI access methods. Note that we support using
- * both PCI BIOS and direct access, with a preference for direct.
- */
+ int bus;
+ physdev_op_t op;
+
+ if ( !pci_probe )
+ return;
- pci_root_ops = pci_check_xen();
- pci_config_read = pci_confx_read;
+ pci_root_ops = &pci_conf_xen;
+ pci_config_read = pci_confx_read;
pci_config_write = pci_confx_write;
- return;
-}
+ pcibios_set_cacheline_size();
-void __init pcibios_init(void)
-{
- if (!pci_root_ops)
- pcibios_config_init();
- if (!pci_root_ops) {
+ op.cmd = PHYSDEVOP_PCI_PROBE_ROOT_BUSES;
+ if ( HYPERVISOR_physdev_op(&op) != 0 )
+ {
printk(KERN_WARNING "PCI: System does not support PCI\n");
return;
}
- pcibios_set_cacheline_size();
-
printk(KERN_INFO "PCI: Probing PCI hardware\n");
-
- if (!pci_using_acpi_prt) {
- pci_root_bus = pcibios_scan_root(0);
- pcibios_irq_init();
- pcibios_fixup_peer_bridges();
- pcibios_fixup_irqs();
- }
+ for ( bus = 0; bus < 256; bus++ )
+ if ( test_bit(bus, &op.u.pci_probe_root_buses.busmask[0]) )
+ (void)pcibios_scan_root(bus);
pcibios_resource_survey();
}
-char * __devinit pcibios_setup(char *str)
+char * __devinit pcibios_setup(char *str)
{
- if (!strcmp(str, "off")) {
+ if ( !strcmp(str, "off") )
pci_probe = 0;
- return NULL;
- }
return NULL;
}
unsigned int pcibios_assign_all_busses(void)
{
- return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
+ return 0;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
int err;
+ u8 pin;
+ physdev_op_t op;
- if ((err = pcibios_enable_resources(dev, mask)) < 0)
+ /* Inform Xen that we are going to use this device. */
+ op.cmd = PHYSDEVOP_PCI_INITIALISE_DEVICE;
+ op.u.pci_initialise_device.bus = dev->bus->number;
+ op.u.pci_initialise_device.dev = PCI_SLOT(dev->devfn);
+ op.u.pci_initialise_device.func = PCI_FUNC(dev->devfn);
+ if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
return err;
- pcibios_enable_irq(dev);
+ /* Now we can bind to the very final IRQ line. */
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &pin);
+ dev->irq = pin;
+
+ /* Turn on device I/O and memory access as necessary. */
+ if ( (err = pcibios_enable_resources(dev, mask)) < 0 )
+ return err;
+
+ /* Sanity-check that an interrupt-producing device is routed to an IRQ. */
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if ( pin != 0 )
+ {
+ if ( dev->irq != 0 )
+ printk(KERN_INFO "PCI: Obtained IRQ %d for device %s\n",
+ dev->irq, dev->slot_name);
+ else
+ printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of "
+ "device %s.\n", 'A' + pin - 1, dev->slot_name);
+ }
return 0;
}
cd ../../arch/xen/kernel
ln -sf ../../i386/kernel/i387.c
ln -sf ../../i386/kernel/init_task.c
+ln -sf ../../i386/kernel/pci-dma.c
+ln -sf ../../i386/kernel/pci-i386.c
+ln -sf ../../i386/kernel/pci-i386.h
ln -sf ../../i386/kernel/ptrace.c
ln -sf ../../i386/kernel/semaphore.c
ln -sf ../../i386/kernel/sys_i386.c